<template>
  <a-form ref="formRef" :rules="rules" :model="modelValue">
    <a-row :gutter="16">
      <a-col v-for="item in items" :key="item.key" :span="item.span || 24">
        <a-form-item :label="item.label" :name="item.key">
          <slot :name="item.key">
            <component
              :is="getComponent(item)"
              v-bind="getProps(item)"
              v-model:value="modelValue[item.key]"
            />
          </slot>
        </a-form-item>
      </a-col>
    </a-row>
  </a-form>
</template>

<script setup lang="ts">
import { computed } from "vue"
import { Input, InputNumber, Select, type FormInstance } from "ant-design-vue"
import { useTemplateRef } from "vue"
const props = defineProps(["formItems", "rules"])
import { omit } from "lodash-es"

const formInstance = useTemplateRef<FormInstance>("formRef")

const modelValue = defineModel()

const componentMap = {
  input: Input,
  number: InputNumber,
  select: Select,
}

const rootProps = ["label", "key", "type"]

function getProps(item) {
  if (item.props) return item.props
  return omit(item, rootProps)
}

defineExpose({
  validate(...args) {
    return formInstance.value.validate(...args)
  },
  resetFields() {
    return formInstance.value.resetFields()
  },
})

const items = computed(() => props.formItems.filter(item => !item.hidden))

function getComponent(item) {
  const { type } = item
  /**
   * type 是一个函数 或 一个对象
   *
   */
  if (type && typeof type !== "string") {
    return type
  }

  return componentMap[type || "input"]
}
</script>

<style scoped></style>
